package com.xymtop.sqlcater.core.sql.sqlparser.tosql.parse;


import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql.AppContent;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql.Element;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql.SqlNode;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql.SqlNodeType;
import lombok.Data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//解析sql节点
@Data
public class Parser {

    //待解析的内容
    private List<Element> elementList = new ArrayList<>();

    //中间储存的内容map
    private Map<String,Element> elementMap = new HashMap<>();


    //解析完毕的内容
    private List<Element> elements = new ArrayList<>();

    //是否已经解析完毕
    private Boolean isParse = false;


    //开启解析
    public Parser parse() throws IOException {

        if(!elementList.isEmpty()){
            for(Element element : elementList){
                //构造map
                elementMap.put(element.getName(),element);
            }

            //开始执行解析
          Execparse(elementList, elementMap);
        }

        return this;
    }



    //解析单个节点
    public  Element ParseElement(Element element) throws IOException {
        //判断是否已经解析过
        if(!element.getIsParse()){
            //没有解析过，开始解析
            List<SqlNode> sqlNodes = element.getSqlNodes();

            //结果的SQL节点
            List<SqlNode> resSqlNodes = new ArrayList<>();

            //解析SQLnode
            if(!sqlNodes.isEmpty()){

                for(SqlNode sqlNode : sqlNodes){

                    //判断sqlnode是否被解析
                    if(!sqlNode.getIsParse()){

                        //单独解析节点
                        sqlNode = parseSqlNode(sqlNode);

                        if(sqlNode.getIsParse()){

                            //添加到结果节点
                            resSqlNodes.add(sqlNode);
                        }

                    }

                }

            }


            //全部解析完毕，替换解析结果
            if (resSqlNodes.size() == element.getSqlNodes().size()) {
                element.setSqlNodes(resSqlNodes);
            }


            element.setIsParse(true);
        }
        return element;
    }

    //开始解析
    public void Execparse(List<Element> elementList, Map<String,Element> elementMap) throws IOException {
        if(!elementList.isEmpty()){

            //判断是否储存成功
            if(!elementMap.isEmpty()){

                //开始遍历并且解析
                for(Element element : elementList){

                    if(!element.getIsParse()){
                        //节点没有被解析过，直接解析
                        element =ParseElement(element);

                        if(element.getIsParse()){
                            //如果已经修改了，需要及时更新数据
                            elementMap.put(element.getName(),element);
                        }

                    }

                    if(element.getIsParse()){
                        //已经确认解析过，添加到结果集
                        this.elements.add(element);
                    }
                }

                //全部解析完毕
                this.isParse = true;

            }
        }


    }


    //解析sql节点
    public SqlNode parseSqlNode(SqlNode sqlNode) throws IOException {
        //判断需要解析的类型
        if(sqlNode.getType()== SqlNodeType.VALUE){

            //因为是变量类型，使用需要先切割变量名称
            String name = sqlNode.getName().substring(1,sqlNode.getName().length());


            //值类型，查找值即可
            Element tempElement = elementMap.get(name);

            if(tempElement!=null) {
                if (tempElement.getIsParse()) {
                    //已经解析过了，直接赋值
                    sqlNode.setSql(tempElement.getBuildSql());
                    sqlNode.setIsParse(true);
                } else {
                    //没有解析过，循环
                    tempElement = ParseElement(tempElement);


                    //更新map
                    elementMap.put(tempElement.getName(), tempElement);

                    //下面对节点进行赋值
                    sqlNode.setSql(tempElement.getBuildSql());
                    sqlNode.setIsParse(true);
                }
            }

            //集合类型的处理
        }else  if(sqlNode.getType()==SqlNodeType.COLLECTION){
            if(!sqlNode.getIsParse()){
                //解析
                String name = sqlNode.getName().substring(1,sqlNode.getName().length());

                Element tempElement = elementMap.get(name);
                if(tempElement!=null){

                if(tempElement.getIsParse()){
                    //已经解析过了，直接赋值
                    sqlNode.setSql(tempElement.getBuildSql());
                    sqlNode.setIsParse(true);
                }else {
                    //没有解析过，循环
                    tempElement  = ParseElement(tempElement);

                    if(tempElement.getIsParse()){

                        //更新map
                        elementMap.put(tempElement.getName(),tempElement);

                        //下面对节点进行赋值
                        sqlNode.setSql(tempElement.getBuildSql());
                        sqlNode.setIsParse(true);
                    }

                }

                //因为是集合类型，使用加个括号
                if(sqlNode.getIsParse()){
                    sqlNode.setSql("("+sqlNode.getSql()+") AS "+sqlNode.getName().substring(1,sqlNode.getName().length()));
                }

             }
            }

            //普通字符串类型
        }else if(sqlNode.getType() == SqlNodeType.NORMAL) {
            sqlNode.setSql(sqlNode.getValue());
            sqlNode.setIsParse(true);
        }

        return  sqlNode;
    }

    public static Parser add(List<Element> elementList){
        Parser sqlNodeParse = new Parser();
        sqlNodeParse.setElementList(elementList);
        return sqlNodeParse;
    }
}
